/**
 * 验证工具类
 *
 * 1. is 开头内容， 验证内容是否正确, function isXX(string) => boolean
 * if (isPassword('123456'))
 *
 * 2. Validator 结尾， 提供用表单验证, function xxValidator() => Rule
 * const rules = { password: { required: true, validator: passwordValidator } }
 */

import type { InternalRuleItem, Value } from 'async-validator/dist-types/interface'

/**
 * async-validator 验证包装
 * @param test  验证是否通过
 * @param message 错误信息，非空 或 test() 不通过提示信息. test() 时 ruleMessage 优于此项
 * @param ruleMessage test() 不通过提示该信息
 */
export const wrapValidator = (
  test: (value: string) => boolean,
  message: string,
  ruleMessage?: string,
) => (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void) => {
  // 非必填
  if (!rule.required && !value) {
    callback()
    return
  }

  const msg = (rule.message && typeof rule.message === 'string') ? rule.message : message

  // 必填报错
  if (!value) {
    callback(msg)
    return
  }

  // 规则校验不通过
  if (!test(value)) {
    callback(ruleMessage || msg)
    return
  }
  callback()
}

const isUsername = (value: string) => /^[a-zA-Z][a-zA-Z0-9]{5,19}$/.test(value)

export const usernameValidator = wrapValidator(isUsername, '用户名不能为空', '无效的用户名')

export const isPassword = (value: string) => /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[^\da-zA-Z\s]).{8,15}$/.test(value)

export const passwordValidator = wrapValidator(isPassword, '请输入您的密码', '无效的密码')

export function confirmPasswordValidator (password: string, confirmPassword: string) {
  return wrapValidator(() => password === confirmPassword, '确认密码不能为空', '两次输入密码不一致')
}

// 手机号，中国大陆
// export const isMobile = (value: string) => /^1[356789]\d{9}$/.test(value)

// 手机号，全中国，包括港澳台
// export const isMobile = (value: string) => /^1[3-8]\d{9}$|^([6|9])\d{7}$|^6([8|6])\d{5}$/.test(value)
export const isMobile = (value: string) => /^((\+|00)86)?1[3-9]\d{9}$|^852\d{8}$|^853\d{8}$|^(886|0)9\d{8}$/.test(value)

// 固话
export const isTel = (value: string) => /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/.test(value)

// 中文简体姓名
export const isChineseName = (value: string) => /^[\u4e00-\u9fa5]{2,6}$/.test(value)

// 社会统一代码
export const isUnifiedCode = (value: string) => /^[0-9A-Za-z]{18}$/.test(value)

/**
 * 微信号
 微信官方定义的微信号规则
 1、可使用 6-20 个字母、数字、下划线和减号；
 2、必须以字母开头（字母不区分大小写）；
 3、不支持设置中文。
 */
export const isWeixin = (value: string) => /^[a-zA-Z][a-zA-Z\d_-]{5,19}$/.test(value)

// 移动电话
export const isPhone = (value: string) => isMobile(value) || isTel(value)

export const phoneValidator = wrapValidator(isPhone, '联系方式不能为空', '无效的联系方式')

export const mobileValidator = wrapValidator(isMobile, '手机号不能为空', '无效的手机号')

export const chineseNameValidator = wrapValidator(isChineseName, '姓名不能为空', '无效的姓名')

export const weixinValidator = wrapValidator(isWeixin, '微信号不能为空', '无效的微信号')

export const unifiedCodeValidator = wrapValidator(isUnifiedCode, '社会统一代码不能为空', '无效的社会统一代码')

export const isEmail = (value: string) => /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}])|(([a-zA-Z\-\d]+\.)+[a-zA-Z]{2,}))$/.test(value)

export const emailValidator = wrapValidator(isEmail, '电子邮箱不能为空', '无效的电子邮箱')

/**
 * 判断url是否是http或https
 * @param {string} url
 * @returns {Boolean}
 */
export function isHttp (url: string) {
  return url.includes('http://') || url.includes('https://')
}

/**
 * 判断path是否为外链
 * @param {string} path
 * @returns {Boolean}
 */
export function isExternal (path: string) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

/**
 * 是否金额
 * @param value
 */
const isMoney = (value: string) => /^(([1-9][0-9]*)|(0\.\d{1,2}|[1-9][0-9]*\.\d{1,2}))$/.test(value)

export const moneyValidator = wrapValidator(isMoney, '请输入金额（元）', '请输入数字保留两位小数')

export function isIdCard (value: string) {
  return /(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|(^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$)/.test(value)
}

export const idCardValidator = wrapValidator(isIdCard, '请输入身份证号', '无效的身份证号')

/**
 * 是否链接
 * @param url
 */
export function isLink (url: any) {
  return url.includes('://') || url.startsWith('http') || url.startsWith('data:') || url.startsWith('/static/') || url.startsWith('wxfile')
}
